package com.yzg.study.kafka.common.base;

import com.yzg.study.kafka.common.exception.ServiceException;
import com.yzg.study.kafka.common.exception.exceptioncode.BaseExceptionCode;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;

import java.io.Serializable;

/**
 * 通用返回信息实体.
 *
 * @author yzg
 * @version v1.0
 */
@Data
@ToString
public class R<T> implements Serializable {

    public static final String DEF_ERROR_MESSAGE = "系统繁忙，请稍候再试";
    public static final String HYSTRIX_ERROR_MESSAGE = "请求超时，请稍候再试";
    public static final int SUCCESS_CODE = 0;
    public static final int FAIL_CODE = -1;
    public static final int TIMEOUT_CODE = -2;
    public static final int VALID_EX_CODE = -9;
    public static final int OPERATION_EX_CODE = -10;
    @ApiModelProperty("响应编码:0或200-请求处理成功")
    private int code;
    @ApiModelProperty("响应数据")
    private T data;
    @ApiModelProperty("提示消息")
    private String msg = "ok";
    @ApiModelProperty("响应时间戳")
    private long timestamp = System.currentTimeMillis();

    private R() {
        this.timestamp = System.currentTimeMillis();
    }

    public R(T data) {
        this.code = SUCCESS_CODE;
        this.data = data;
    }

    public R(int code, T data, String msg) {
        this.code = code;
        this.data = data;
        this.msg = msg;
        this.timestamp = System.currentTimeMillis();
    }

    public static <E> R<E> result(int code, E data, String msg) {
        return new R<E>(code, data, msg);
    }

    public static <E> R<E> success(E data) {
        return new R<E>(SUCCESS_CODE, data, "ok");
    }

    public static R<Boolean> success() {
        return new R<Boolean>(SUCCESS_CODE, true, "ok");
    }

    public static <E> R<E> successDef(E data) {
        return new R<E>(SUCCESS_CODE, data, "ok");
    }

    public static <E> R<E> successDef() {
        return new R<E>(SUCCESS_CODE, null, "ok");
    }

    public static <E> R<E> successDef(E data, String msg) {
        return new R<E>(SUCCESS_CODE, data, msg);
    }

    public static <E> R<E> success(E data, String msg) {
        return new R<E>(SUCCESS_CODE, data, msg);
    }

    public static <E> R<E> fail(int code, String msg) {
        return new R<E>(code, null, msg != null && !msg.isEmpty() ? msg : "系统繁忙，请稍候再试");
    }

    public static <E> R<E> fail(String msg) {
        return fail(-10, msg);
    }

    public static <E> R<E> fail(int code, String msg, Object... args) {
        String message = msg != null && !msg.isEmpty() ? msg : "系统繁忙，请稍候再试";
        return new R<E>(code, null, String.format(message.replaceAll("\\{\\}", "%\\s"), args));
    }

    public static <E> R<E> fail(String msg, Object... args) {
        String message = msg != null && !msg.isEmpty() ? msg : "系统繁忙，请稍候再试";
        return new R<E>(-10, null, String.format(message, args));
    }

    public static <E> R<E> fail(BaseExceptionCode exceptionCode) {
        return validFail(exceptionCode);
    }

    public static <E> R<E> fail(ServiceException exception) {
        return exception == null ? fail("系统繁忙，请稍候再试") : new R<>(exception.getCode(), null, exception.getMessage());
    }

    public static <E> R<E> fail(Throwable throwable) {
        return fail(-1, throwable != null ? throwable.getMessage() : "系统繁忙，请稍候再试");
    }

    public static <E> R<E> validFail(String msg) {
        return new R<E>(-9, null, msg != null && !msg.isEmpty() ? msg : "系统繁忙，请稍候再试");
    }

    public static <E> R<E> validFail(String msg, Object... args) {
        String message = msg != null && !msg.isEmpty() ? msg : "系统繁忙，请稍候再试";
        return new R<E>(-9, null, String.format(message, args));
    }

    public static <E> R<E> validFail(BaseExceptionCode exceptionCode) {
        return new R<E>(exceptionCode.getCode(), null, exceptionCode.getMsg() != null &&
                !exceptionCode.getMsg().isEmpty() ? exceptionCode.getMsg() : "系统繁忙，请稍候再试");
    }

    public static <E> R<E> timeout() {
        return fail(-2, "请求超时，请稍候再试");
    }


    public Boolean isSuccess() {
        return this.code == 0 || this.code == 200;
    }

    public int getCode() {
        return this.code;
    }

    public T getData() {
        return this.data;
    }

    public String getMsg() {
        return this.msg;
    }

    public long getTimestamp() {
        return this.timestamp;
    }

    public R<T> setCode(int code) {
        this.code = code;
        return this;
    }

    public R<T> setData(T data) {
        this.data = data;
        return this;
    }

    public R<T> setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    public R<T> setTimestamp(long timestamp) {
        this.timestamp = timestamp;
        return this;
    }
}
